<script setup>
import * as XLSX from 'xlsx';
import { computed, onMounted, watch, ref, getCurrentInstance } from 'vue';
const { proxy } = getCurrentInstance();
const emits = defineEmits(['update:modelValue','ClearSource']);


function handleClose() {
  emits('ClearSource')
  // 关闭热力图图层
  heatMapLayer &&  heatMapLayer.getSource().clear()
  heatMapLayer = null;
}

let map = null;
onMounted(() => {
  map = proxy.$map;
});
// 获取数据做一个映射 
const accidentLevel = {
  1: '严重事故',
  2: '中等事故',
  3: '轻度事故',
  4: '轻微事故',
};
const handleStatus = {
  0: '待处理',
  1: '正在处理',
  2: '已处理',
};
/* 接收父组件showDialog */
const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false,
  },
  searchData: {
    type: Array,
    default: [],
  },
});
const dialogOverflowVisible = computed({
  get() {
    return props.modelValue;
  },
  set(val) {
    if (val === false) {
      //关闭模态框时，重置分页器，目前位置val只会为false
      currentPage.value = 1;
    }
    // 单向数据流,子组件的计算属性的set方法修改父组件的值
    emits('update:modelValue', val);
  },
});
/* 分页器逻辑 */
const limit = 8;
const currentPage = ref(1);
// 更新currentPage
const handleCurrentChange = (val) => {
  currentPage.value = val;
};
/* 表格的数据由以下计算属性得到*/
const tableData = computed(() => {
  // console.log(props.searchData);
  // 用于存储搜索结果
  const result = props.searchData;
  // 分页slice得到每一页数据的逻辑,也写在computed中
  const start = (currentPage.value - 1) * 8;
  const end = start + limit;
  return result.slice(start, end).map((item) => {
    return {
      事件编号: item.values_.values_.事件编号,
      事件类型: item.values_.values_.事件类型,
      事件等级: accidentLevel[item.values_.values_.事件等级],
      发生时间: item.values_.values_.发生时间,
      发生地点: item.values_.values_.发生地点,
      车牌号: item.values_.values_.车牌号,
      驾驶员: item.values_.values_.驾驶员,
      处理状态: handleStatus[item.values_.values_.处理状态],
    };
  });
});
/* 热力图 */
let heatMapLayer = null;
const addHeatMap = () => {
  // console.log(props.searchData) // 获取到要素
  // 如果存在热力图层,就移除它,并把热力图层设置为空,否则下一次点击无法生成热力图,
  if (heatMapLayer) {
    map.removeLayer(heatMapLayer);
    // heatMapLayer.getSource().clear();这个代码也可以
    heatMapLayer = null;
    return;
  }
  /* 对查询到的数据重新处理,每个要素添加一个weight属性 */
  const heatFeatures = props.searchData.map((feature) => {
    feature.set('weight', feature.values_.values_.事件等级 * 0.25);
    return feature;
  });
  heatMapLayer = new ol.layer.Heatmap({
    source: new ol.source.Vector({
      features: heatFeatures,
    }),
    /* 模糊 */
    blur: 10,
    /* 半径 */
    radius: 15,
    /* 权重 0~1之间 */
    /* 热力图的 weight 需要根据不同的事件等级设置不同的权重 */
    weight: function (feature) {
      return feature.get('weight');
    },
  });
  map.addLayer(heatMapLayer);
};
/* 点击查看统计图触发的函数
      1)获取事件数量
      2)显示隐藏统计图
      3)处理统计图数据--折线图数据
      4)处理统计图数据--饼图数据
*/
let openChartValue = ref(false);
let eventCount = ref('');
let lineData = ref({}); // 折线图数据
let pieDataArr = ref([]); // 饼图数据
const changeOpenChart = () => {
  // 1)获取事件数量
  eventCount.value = props.searchData.length;
  // 2)显示隐藏
  openChartValue.value = !openChartValue.value;
  // 3)处理统计图数据 --- 折线图数据
  // console.log(props.searchData);
  const chartData = props.searchData.map((item) => item.values_.values_);
  // console.log(chartData)
  // 循环12个月份,生成每个月份每个事件初始值为0的初始数据
  for (let i = 1; i <= 12; i++) {
    lineData.value[i + '月'] = {
      翻车: 0,
      刮擦: 0,
      碾压: 0,
      碰撞: 0,
      其他: 0,
      失火: 0,
    };
  }
  // console.log(lineData.value);
  chartData.forEach((event) => {
    // console.log(event);
    const timeStr = event.发生时间.split(' ')[0]; // 获取拉框数据的所有时间
    const [year, month, day] = timeStr.split('.'); // 分割年、月、日
    const monthStr = parseInt(month) + '月'; // 去掉个位数前面的0
    // console.log(monthStr);
    lineData.value[monthStr][event.事件类型]++; // 对[拉框数据]的月份和事件类型的对应的数量进行累加
  });
  //4)处理统计图数据--饼图数据
  let num1 = chartData.filter((item) => item.事件类型 == '翻车').length;
  let num2 = chartData.filter((item) => item.事件类型 == '刮擦').length;
  let num3 = chartData.filter((item) => item.事件类型 == '碾压').length;
  let num4 = chartData.filter((item) => item.事件类型 == '碰撞').length;
  let num5 = chartData.filter((item) => item.事件类型 == '其他').length;
  let num6 = chartData.filter((item) => item.事件类型 == '失火').length;
  pieDataArr.value = [num1, num2, num3, num4, num5, num6];
  // console.log(pieDataArr.value);
};
/* 统计图配置项---折线图堆叠*/
/* 这里的配置项是动态的,所以用计算属性保持响应性 */
const optionStackedLine = computed(() => {
  return {
    title: {
      text: `交通事件(${eventCount.value})起`,
    },
    tooltip: {
      trigger: 'axis',
    },
    legend: {
      data: ['翻车', '刮擦', '碾压', '碰撞', '其他', '失火'],
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      containLabel: true,
    },
    toolbox: {
      feature: {
        saveAsImage: {},
      },
    },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: [
        '一月',
        '二月',
        '三月',
        '四月',
        '五月',
        '六月',
        '七月',
        '八月',
        '九月',
        '十月',
        '十一月',
        '十二月',
      ],
    },
    yAxis: {
      type: 'value',
    },
    series: [
      {
        name: '翻车',
        type: 'line',
        stack: 'Total',
        data: [
          lineData.value['1月']['翻车'],
          lineData.value['2月']['翻车'],
          lineData.value['3月']['翻车'],
          lineData.value['4月']['翻车'],
          lineData.value['5月']['翻车'],
          lineData.value['6月']['翻车'],
          lineData.value['7月']['翻车'],
          lineData.value['8月']['翻车'],
          lineData.value['9月']['翻车'],
          lineData.value['10月']['翻车'],
          lineData.value['11月']['翻车'],
          lineData.value['12月']['翻车'],
        ],
      },
      {
        name: '刮擦',
        type: 'line',
        stack: 'Total',
        data: [
          lineData.value['1月']['刮擦'],
          lineData.value['2月']['刮擦'],
          lineData.value['3月']['刮擦'],
          lineData.value['4月']['刮擦'],
          lineData.value['5月']['刮擦'],
          lineData.value['6月']['刮擦'],
          lineData.value['7月']['刮擦'],
          lineData.value['8月']['刮擦'],
          lineData.value['9月']['刮擦'],
          lineData.value['10月']['刮擦'],
          lineData.value['11月']['刮擦'],
          lineData.value['12月']['刮擦'],
        ],
      },
      {
        name: '碾压',
        type: 'line',
        stack: 'Total',
        data: [
          lineData.value['1月']['碾压'],
          lineData.value['2月']['碾压'],
          lineData.value['3月']['碾压'],
          lineData.value['4月']['碾压'],
          lineData.value['5月']['碾压'],
          lineData.value['6月']['碾压'],
          lineData.value['7月']['碾压'],
          lineData.value['8月']['碾压'],
          lineData.value['9月']['碾压'],
          lineData.value['10月']['碾压'],
          lineData.value['11月']['碾压'],
          lineData.value['12月']['碾压'],
        ],
      },
      {
        name: '碰撞',
        type: 'line',
        stack: 'Total',
        data: [
          lineData.value['1月']['碰撞'],
          lineData.value['2月']['碰撞'],
          lineData.value['3月']['碰撞'],
          lineData.value['4月']['碰撞'],
          lineData.value['5月']['碰撞'],
          lineData.value['6月']['碰撞'],
          lineData.value['7月']['碰撞'],
          lineData.value['8月']['碰撞'],
          lineData.value['9月']['碰撞'],
          lineData.value['10月']['碰撞'],
          lineData.value['11月']['碰撞'],
          lineData.value['12月']['碰撞'],
        ],
      },
      {
        name: '其他',
        type: 'line',
        stack: 'Total',
        data: [
          lineData.value['1月']['其他'],
          lineData.value['2月']['其他'],
          lineData.value['3月']['其他'],
          lineData.value['4月']['其他'],
          lineData.value['5月']['其他'],
          lineData.value['6月']['其他'],
          lineData.value['7月']['其他'],
          lineData.value['8月']['其他'],
          lineData.value['9月']['其他'],
          lineData.value['10月']['其他'],
          lineData.value['11月']['其他'],
          lineData.value['12月']['其他'],
        ],
      },
      {
        name: '失火',
        type: 'line',
        stack: 'Total',
        data: [
          lineData.value['1月']['失火'],
          lineData.value['2月']['失火'],
          lineData.value['3月']['失火'],
          lineData.value['4月']['失火'],
          lineData.value['5月']['失火'],
          lineData.value['6月']['失火'],
          lineData.value['7月']['失火'],
          lineData.value['8月']['失火'],
          lineData.value['9月']['失火'],
          lineData.value['10月']['失火'],
          lineData.value['11月']['失火'],
          lineData.value['12月']['失火'],
        ],
      },
    ],
  };
});
/* 统计图配置项---扇形图 */
const optionPie = computed(() => {
  return {
    title: {
      text: `交通事件(${eventCount.value})起`,
    },
    tooltip: {
      trigger: 'item',
    },
    legend: {
      orient: 'vertical',
      left: 'right',
    },
    series: [
      {
        name: '事件类型',
        type: 'pie',
        radius: '50%',
        data: [
          { value: pieDataArr.value[0], name: '翻车' },
          { value: pieDataArr.value[1], name: '刮擦' },
          { value: pieDataArr.value[2], name: '碾压' },
          { value: pieDataArr.value[3], name: '碰撞' },
          { value: pieDataArr.value[4], name: '其他' },
          { value: pieDataArr.value[5], name: '失火' },
        ],
        emphasis: {
          itemStyle: {
            shadowBlur: 10,
            shadowOffsetX: 0,
            shadowColor: 'rgba(0, 0, 0, 0.5)',
          },
        },
      },
    ],
  };
});
/* 两种统计图的切换显示 */
const isShowLine = ref(true);
const isShowPie = ref(false);
const changeLine = () => {
  if (!isShowLine.value) {
    isShowLine.value = true;
    isShowPie.value = false;
  }
};
const changePie = () => {
  if (isShowLine.value) {
    isShowLine.value = false;
    isShowPie.value = true;
  }
};
/* 导出excel表 */
const exportExcel = () => {
  // 创建工作簿
  const workbook = XLSX.utils.book_new();
  // 将表格数据转换为工作表
  const worksheet = XLSX.utils.json_to_sheet(tableData.value);
  // 将工作表添加到工作簿
  XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
  // 导出 Excel 文件
  XLSX.writeFile(workbook, 'table_data.xlsx');
};
/* 表格点击飞行到要素 */
const flyToPoint = (事件编号) => {
  // console.log(事件编号); //拿到事件编号
  let center = props.searchData.find(
    (item) => item.values_.values_.事件编号 == 事件编号
  ).values_.geometry.flatCoordinates;
  map.getView().animate({
    center,
    zoom: 18,
    duration: 2000,
  });
};


</script>

<template>
  <el-dialog
    v-model="dialogOverflowVisible"
    width="800px"
    draggable
    overflow
    :modal="false"
    @close="handleClose"
  >
    <!-- 自定义头部 -->
    <template #header>
      <div class="my-header">
        <el-button type="primary" @click="addHeatMap">查看热力图</el-button>
        <el-button type="primary" @click="changeOpenChart"
          >查看统计图</el-button
        >
        <el-button type="primary" @click="exportExcel">导出excel表</el-button>
      </div>
    </template>
    <!-- 统计图,导出excel表 -->
    <el-dialog
      v-model="openChartValue"
      append-to-body
      width="850px"
      draggable
      overflow
    >
      <!-- 自定义头部 -->
      <template #header>
        <div class="my-header">
          <!-- <span>事件统计图</span> -->
          <el-button type="success" @click="changeLine">按月份统计</el-button>
          <el-button type="success" @click="changePie">按类型统计</el-button>
        </div>
      </template>
      <br />
      <!-- 统计图(堆叠折线图和扇形图) -->
      <v-chart
        class="chart"
        :option="optionStackedLine"
        v-if="isShowLine"
      ></v-chart>
      <v-chart class="chart" :option="optionPie" v-if="isShowPie"></v-chart>
    </el-dialog>
    <!-- 查询结果表格 
          :data="tableData" 绑定了表格的数据源;
          label是表格的列名;
          prop是数据源的key值;
          show-overflow-tooltip:当内容太长时,不换行,溢出工具提示;
    -->
    <el-table
      :data="tableData"
      style="width: 100%"
      highlight-current-row="true"
    >
      <el-table-column prop="事件编号" label="事件编号" width="150">
        <!-- 点击事件编号列可以触发函数,这里需要通过默认带的插槽实现,因为el-table-column不是真实的元素,无法点击,无法@click -->
        <template #default="scope">
          <div @click="flyToPoint(scope.row.事件编号)">
            {{ scope.row.事件编号 }}
          </div>
        </template>
      </el-table-column>
      <el-table-column prop="事件类型" label="事件类型" width="80px" />
      <el-table-column prop="事件等级" label="事件等级" />
      <el-table-column prop="发生时间" label="发生时间" show-overflow-tooltip />
      <el-table-column prop="发生地点" label="发生地点" show-overflow-tooltip />
      <el-table-column prop="车牌号" label="车牌号" show-overflow-tooltip />
      <el-table-column prop="驾驶员" label="驾驶员" />
      <el-table-column prop="处理状态" label="处理状态" />
    </el-table>
    <!-- 分页器 
          :current-page="currentPage" 当前页码
          :page-size="limit" 每页显示条数
          :total="props.modalData.attrValues.length" 总条数
          @current-change="handleCurrentChange" 切换页码时触发
    -->
    <el-pagination
      size="small"
      background
      layout="prev, pager, next"
      :page-size="limit"
      :total="props.searchData.length"
      :current-page="currentPage"
      @current-change="handleCurrentChange"
    />
  </el-dialog>
</template>

<style scoped>
.chart {
  width: 800px;
  height: 400px;
}
:deep(.el-table) {
  text-align: center;
}
:deep(.el-table__body tr .cell) {
  line-height: 13px;
}
</style>
